package org.lisen.scdemo.sender.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * @author Administrator
 * @create 2020-02-1521:47
 */
@Service
@Slf4j
public class SenderServiceImpl implements ISenderService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public void send() {
        String msg = "hello rabbitmq "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        log.info("Sender: {}", msg);
        rabbitTemplate.convertAndSend("hello", msg);
    }


    @Override
    public void directExchangeSend() {

        String msg = "rabbitmq direct exchange send msg "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        log.info("使用直接交换机发送消息： {}", msg);
        //direct.exchange是在RabbitMQConfig中定义的Direct型交换机
        rabbitTemplate.convertAndSend("direct.exchange", "direct.exchange.routing.key",msg);

    }


    @Override
    public void topicExchangeSend() {

        String msg = "rabbitmq topic exchange send msg to topic.queue.q1 "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        log.info("使用topic交换机发送消息： {} 到topic.queue.q1队列", msg);
        //topic.exchange是在RabbitMQConfig中定义的Topic型交换机(topic.exchange为声明交换机时的名称)
        rabbitTemplate.convertAndSend("topic.exchange", "topic.queue1.msg", msg);

        String msg2 = "rabbitmq topic exchange send msg to topic.queue.q2 "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        log.info("使用topic交换机发送消息： {} 到topic.queue.q2队列", msg2);
        //topic.exchange是在RabbitMQConfig中定义的Topic型交换机(topic.exchange为声明交换机时的名称)
        rabbitTemplate.convertAndSend("topic.exchange", "topic.queue2.msg", msg2);
    }


    @Override
    public void fanoutExchangeSend() {
        String msg = "rabbitmq fanout exchange send msg "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        log.info("使用fanout交换机发送消息： {}", msg);

        rabbitTemplate.convertAndSend("fanout.exchange", "fanout.routing.key", msg);
    }

    /**
     * 用于演示死信交换机
     */
    @Override
    public void dxlExchangeSend() {
        String msg = "rabbitmq usual exchange send msg "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        log.info("用于演示死信队列, 向usual.exchange交换机发送消息： {}", msg);
        rabbitTemplate.convertAndSend("usual.direct.exchange", "routing.usual.key", msg);
    }


    /**
     * 用于演示演示交换机
     */
    @Override
    public void delayQueue() {
        String msg = "rabbitmq delay queue: send msg "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        log.info("用于演示延迟队列： 向delay.exchange交换机发送消息: {}", msg);
        rabbitTemplate.convertAndSend("delay.exchange", "routing.delay.key", msg);
    }


    @Override
    public void confirmMessage() {

        String msg = "rabbitmq direct exchange send msg and confirm "
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        log.info("使用直接交换机发送消息： {}, 并返回确认", msg);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());

        //rabbitTemplate.setMandatory(true);

        //在消息到达exchange后回复确认消息，如果消息是持久化则在持久化完成后回复
        /*rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData,
                                boolean ack,
                                String cause) {
                if(ack) {
                    log.info("消息到达交换机返回确认 消息ID = {}, 消息内容 = {}",
                            correlationData.getId(),
                            cause);
                } else {
                    log.info("消息发送失败, cause = {}", cause);
                }
            }
        });*/

        //如果需要设置ReturnCallback，则必须设置此项
        //rabbitTemplate.setMandatory(true);

        //在消息通过交换机发送到对应的队列失败时，会回调该方法，可以在此处进行消息重发
        /*rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message,
                                        int replyCode,
                                        String replyText,
                                        String exchange,
                                        String routingKey) {
                log.info("----------------------------------------");
                log.info(message.getBody().toString());
                log.info(replyCode+"");
                log.info(replyText);
                log.info(exchange);
                log.info(routingKey);
                log.info("----------------------------------------");
            }
        });*/

        //direct.exchange是在RabbitMQConfig中定义的Direct型交换机
        rabbitTemplate.convertAndSend(
                "direct.exchange",
                "direct.exchange.routing.key",
                msg,
                correlationData);
    }

}
